package com.youthburin.rmp.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Date;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.Log4jConfigurer;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.youthburin.base.controller.BaseController;
import com.youthburin.base.services.OpLogService;
import com.youthburin.base.util.DwzResponse;
import com.youthburin.base.util.DwzResponseUtils;
import com.youthburin.rmp.enums.RmpOpLogBusiTypeEnum;
import com.youthburin.rmp.enums.RmpOpLogTypeEnum;
import com.youthburin.rmp.util.FileDesc;
import com.youthburin.utils.FileDownLoadUtils;
import com.youthburin.utils.FileOperateUtils;

@Controller
public class LogController extends BaseController {
	@Value("#{settings['log4jproperties.location']}")
	private String location;
	private static final Pattern p = Pattern.compile("^log4j\\.appender\\.(\\w+)\\.File$");
	@Autowired
	@Qualifier("rmpOpLogService")
	private OpLogService opLogService;

	@RequiresPermissions("log:list")
	@RequestMapping(value = "/system/log/show", method = RequestMethod.GET)
	public String showLogger(ModelMap model) throws Exception {
		File folder = getLogsFolder();
		if (folder != null && folder.isDirectory()) {
			File[] files = folder.listFiles();
			if (files != null && files.length > 0) {
				List<FileDesc> fileDescs = new ArrayList<FileDesc>();
				for (File file : files) {
					FileDesc fileDesc = new FileDesc();
					fileDesc.setFileName(file.getName());
					fileDesc.setFilePath(file.getAbsolutePath());
					fileDesc.setFileSize(FileUtils.byteCountToDisplaySize(file.length()));
					fileDesc.setLastModified(new Date(file.lastModified()));

					fileDescs.add(fileDesc);
				}

				model.put("logFiles", fileDescs);
			}
		}
		opLogService.addLog(RmpOpLogTypeEnum.LIST.toString(), RmpOpLogBusiTypeEnum.RMP_LOG.toString());
		return "/system/log/show";
	}

	@RequiresPermissions("log:editconfig")
	@RequestMapping(value = "/system/log/config", method = RequestMethod.GET)
	public String toConfigLog(ModelMap model) {
		try {
			model.put("log4jproperties", FileUtils.readFileToString(getLog4jPropertiesFile()));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return "/system/log/config";
	}

	@RequiresPermissions("log:editconfig")
	@RequestMapping(value = "/system/log/config", method = RequestMethod.POST)
	@ResponseBody
	public DwzResponse configLog(String log4jproperties) {
		try {
			FileUtils.writeStringToFile(getLog4jPropertiesFile(), log4jproperties);
			Log4jConfigurer.initLogging(location);
			opLogService.addLog(RmpOpLogTypeEnum.UPDATE.toString(), RmpOpLogBusiTypeEnum.RMP_LOG.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}
		return DwzResponseUtils.createSuccessResponse(true);
	}

	@RequestMapping(value = "/system/log/download/{fileName}/")
	public void downLoad(@PathVariable("fileName") String fileName, HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		File folder = getLogsFolder();
		if (folder != null && folder.isDirectory()) {
			File file = new File(folder, fileName);
			if (file != null)
				FileDownLoadUtils.downLoadFile(request, response, file);
		}
	}

	@RequiresPermissions("log:console")
	@RequestMapping(value = "/system/log/console", method = RequestMethod.GET)
	public String console(ModelMap model) {
		try {
			File logFile = getCurrentLogFile();
			model.put("logFileContent", "\n");
			model.put("logFileLength", logFile.length());
		} catch (Exception e) {
			e.printStackTrace();
		}
		return "/system/log/console";
	}

	@RequiresPermissions("log:console")
	@RequestMapping(value = "/system/log/ajaxConsole", method = RequestMethod.GET)
	public void ajaxConsole(int start, HttpServletResponse response) throws IOException {
		File logFile = getCurrentLogFile();
		long length = logFile.length();
		if (length > start) {
			String content = FileOperateUtils.readFileAsString(logFile, start, (int) length - 1, "GBK");
			response.setCharacterEncoding("UTF-8");
			response.getWriter().write(String.format("%d-%s", length, content));
			response.getWriter().close();
		}
	}

	// 取当前日志配置文件
	private File getLog4jPropertiesFile() throws IOException {
		return ResourceUtils.getFile(location);
	}

	// 取得日志保存的目录
	private File getLogsFolder() throws IOException {
		File currentLogFile = getCurrentLogFile();
		if (currentLogFile != null)
			return currentLogFile.getParentFile();
		return null;
	}

	// 取当前日志文件
	private File getCurrentLogFile() throws IOException {
		File log4jpropertiesFile = getLog4jPropertiesFile();

		if (log4jpropertiesFile != null) {
			Properties properties = new Properties();
			properties.load(new FileInputStream(log4jpropertiesFile));

			String rootLogger = properties.getProperty("log4j.rootLogger");

			String fileAppendConfig = "";

			for (Object key : properties.keySet()) {
				Matcher matcher = p.matcher((String) key);
				if (matcher.matches()) {
					if (matcher.groupCount() > 0) {
						String fileAppend = matcher.group(1);
						if (rootLogger.contains(fileAppend)) {
							fileAppendConfig = properties.getProperty((String) key);
							break;
						}
					}
				}
			}
			if (StringUtils.isNotBlank(fileAppendConfig))
				return ResourceUtils.getFile(fileAppendConfig);
		}
		return null;
	}

}
